<template>
  <div class="z_table">
    <div class="z_table_head">
      <div class="action_create" v-if="!noAdd">
        <a-button type="primary" @click="handleAdd">{{ addLable }}</a-button>
      </div>
      <div class="action_group">
        <a-select
          v-model:model-value="actionValue"
          placeholder="操作"
          :options="actionGroupOptions"
          style="width: 150px"
        ></a-select>
        <a-button
          v-if="actionValue"
          type="primary"
          status="danger"
          @click="handleAction"
          >执行</a-button
        >
      </div>
      <div class="action_search" v-if="!noActionGroup">
        <a-input-search
          :placeholder="searchPlaceholder"
          @search="search"
          v-model="params.key"
        ></a-input-search>
      </div>
      <div class="action_filter">
        <a-select
          v-for="item in filterGroupOptions"
          :options="item.options"
          :placeholder="item.label"
          :style="{ width: item.width + 'px' }"
          @change="item?.callback"
          allow-clear
        ></a-select>
      </div>
      <div class="action_search_slot">
        <slot name="search_other"></slot>
      </div>

      <div class="ation_refresh" @click="refresh"><icon-refresh /></div>
    </div>
    <div class="z_table_body">
      <a-spin :loading="loading" tip="加载中...">
        <div class="z_table_content">
          <a-table
            @row-click="handleRowClick"
            :row-key="rowKey"
            :row-selection="!props.noCheck ? rowSelection : undefined"
            v-model:selectedKeys="selectedKeys"
            :columns="columns"
            :data="data.list"
            :pagination="false"
          >
            <template #columns>
              <template v-for="col in props.columns">
                <a-table-column
                  v-if="col.dataIndex"
                  v-bind="col"
                ></a-table-column>

                <a-table-column v-else-if="col.slotName" v-bind="col">
                  <template #cell="data">
                    <div class="col_actions" v-if="col.slotName === 'action'">
                      <slot v-bind="data" name="action_left"></slot>
                      <a-button
                        v-if="!noEdit"
                        type="primary"
                        @click="handleUpdate(data.record)"
                        >{{ editLable }}</a-button
                      >
                      <a-popconfirm
                        @ok="handleDelete(data.record)"
                        content="确认删除该记录吗？"
                      >
                        <a-button
                          type="primary"
                          status="danger"
                          v-if="!noDelete"
                          >{{ delLable }}</a-button
                        >
                      </a-popconfirm>
                      <slot v-bind="data" name="action_right"></slot>
                    </div>
                    <div v-if="col.slotName === 'created_at'">
                      {{
                        dateCustomFormat(
                          data.record[col.slotName],
                          col.dateFormat
                        )
                      }}
                    </div>
                    <slot :name="col.slotName" v-bind="data" v-else></slot>
                  </template>
                </a-table-column>
              </template>
            </template>
          </a-table>
        </div>
        <div v-if="!noPagnation" class="z_table_pagination">
          <a-pagination
            :total="data.count"
            v-model:current="params.page"
            v-model:page-size="params.limit"
            show-total
            @change="onPageChange"
          />
        </div>
      </a-spin>
    </div>
    <z-modal-form
      v-if="props.formList?.length"
      ref="modalFormRef"
      :visible="visible"
      :form-list="props.formList"
      :addLabel="props.addFormLabel"
      :editLabel="props.editFormLabel"
      @create="handleModalCreateOk"
      @update="handleModalUpdateOk"
      @cancel="handleCancel"
    ></z-modal-form>
  </div>
</template>

<script lang="ts" setup>
import type { BaseResponse, listResponse, paramsType } from "@/api/index.d";
import {
  Message,
  type TableColumnData,
  type TableRowSelection,
} from "@arco-design/web-vue";
import { ref, reactive, toValue } from "vue";
import type { dateTemType } from "@/utils/date";
import { dateCustomFormat } from "@/utils/date";
import {
  baseDeleteApi,
  basePostApi,
  basePutApi,
  type optionsFunc,
  type optionsType,
} from "@/api";
import { MsgEnum } from "@/enum/msg";
import ZModalForm from "@/components/admin/modalForm/index.vue";
import type { formItemType } from "../modalForm/index.vue";

interface Props {
  url: (params?: paramsType) => Promise<BaseResponse<listResponse<any>>>;
  columns: columnType[];
  aticonGroups?: actionGroupType[];
  filterGroups?: filterGroupType[];
  rowKey?: string;
  noDefaultDelete?: boolean;
  noAdd?: boolean;
  noEdit?: boolean;
  noDelete?: boolean;
  noBatchDelete?: boolean; //是否没有批量删除
  noActionGroup?: boolean;
  noCheck?: boolean;
  noPagnation?: boolean;
  searchPlaceholder?: string;
  addLable?: string;
  editLable?: string;
  delLable?: string;
  limit?: number;
  formList: formItemType[];
  addFormLabel: string;
  editFormLabel?: string;
}

const visible = ref(false);
const modalFormRef = ref();

const handleCancel = (val: boolean) => {
  visible.value = false;
};
const handleModalCreateOk = async (formData: any, fn: any) => {
  console.log(formData, "createformData");

  const array = /\"(.*?)\"/.exec(props.url.toString());
  if (array?.length !== 2) {
    return;
  }
  const url = array[1];
  try {
    await basePostApi(url, formData);
    Message.success("新增成功");
    getList();
    fn(true);
  } catch (err) {
    Message.error(MsgEnum.fail);
    fn(false);
  }
};
const handleModalUpdateOk = async (formData: any, fn: any) => {
  console.log(formData, "updateformData");
  // fn(false);
  const array = /\"(.*?)\"/.exec(props.url.toString());
  if (array?.length !== 2) {
    return;
  }
  const url = array[1];
  try {
    await basePutApi(url, formData);
    Message.success("更新成功");
    getList();
    fn(true);
  } catch (err) {
    Message.error(MsgEnum.fail);
    fn(false);
  }
};

export interface actionGroupType {
  label: string;
  value?: number;
  callback: (keyList: string[] | number[]) => void;
}
const actionGroupOptions = reactive<actionGroupType[]>([]);

export interface filterGroupType {
  label: string;
  source: optionsType[] | optionsFunc;
  options?: optionsType[];
  params?: paramsType;
  column?: string;
  callback?: (value: number | string) => void;
  width?: number;
}

const filterGroupOptions = reactive<filterGroupType[]>([]);

const props = defineProps<Props>();
const actionValue = ref();
const emits = defineEmits<{
  delete: [idList: number[] | string[]];
  add: any;
  edit: [record: any];
  rowClick: [record: any, e: Event];
}>();
const {
  rowKey = "code",
  noDefaultDelete,
  noAdd,
  noEdit,
  noDelete,
  noBatchDelete,
  aticonGroups,
  filterGroups,
  noPagnation,
  searchPlaceholder = "请搜索",
  addLable = "创建",
  editLable = "编辑",
  delLable = "删除",
  limit = 10,
} = props;

const initActionGroup = () => {
  let index = 0;
  if (!noBatchDelete) {
    actionGroupOptions.unshift({
      label: "批量删除",
      value: 1,
      callback: (keyList: string[] | number[]) => {
        baseDelete(keyList);
        selectedKeys.value = [];
      },
    });
    index = 1;
  }
  index++;
  for (const action of props.aticonGroups || []) {
    actionGroupOptions.push({
      label: action.label,
      value: index,
      callback: action.callback,
    });
  }
};
initActionGroup();
const initfilterGroup = async () => {
  for (const filter of props.filterGroups || []) {
    if (typeof filter.source === "function") {
      const res = await filter.source(filter.params);
      if (res.code != 0) {
        Message.error(res.message);
        continue;
      }
      filter.options = res.data;
    } else {
      filter.options = filter.source;
    }

    if (!filter.callback) {
      filter.callback = (value) => {
        console.log(value, "value");

        if (filter.column) {
          const p: { [key: string]: any } = {};
          p[filter.column] = value;
          getList(p);
        }

        console.log("父组件没有callback，子组件添加回调函数");
      };
    }

    filterGroupOptions.push(filter);
  }
};
initfilterGroup();

const handleAdd = () => {
  if (props.formList?.length) {
    visible.value = true;
    return;
  }
  emits("add");
};
const handleUpdate = (record: any) => {
  if (props.formList?.length) {
    modalFormRef.value.setForm(record);
    visible.value = true;
    return;
  }
  emits("edit", record);
};
const handleRowClick = (record: any, e: Event) => {
  emits("rowClick", record, e);
};

export interface columnType extends TableColumnData {
  dateFormat?: dateTemType;
}

const loading = ref(false);

const data = reactive<listResponse<any>>({
  list: [],
  count: 0,
});

const params = reactive<paramsType>({
  key: "",
  limit: !noPagnation ? limit : -1,
  page: 1,
  sort: "",
});

const onPageChange = () => {
  getList();
};

const search = () => {
  getList();
};

const refresh = () => {
  getList();
  Message.success("刷新成功");
};

const getList = async (newparams?: paramsType) => {
  loading.value = true;
  if (newparams) {
    Object.assign(params, newparams);
  }
  try {
    const { data: resData } = await props.url(params);
    data.list = resData.list || [];
    data.count = resData.count;
  } catch (error) {
    Message.error("获取列表失败");
  } finally {
    loading.value = false;
  }
};
defineExpose({
  getList,
  data,
});

const handleDelete = async (row: any) => {
  const key = row[rowKey];
  baseDelete([key]);
};

const baseDelete = async (keyList: number[] | string[]) => {
  if (noDefaultDelete) {
    emits("delete", keyList);
  } else {
    const array = /\"(.*?)\"/.exec(props.url.toString());
    if (array?.length !== 2) {
      return;
    }
    const url = array[1];
    try {
      await baseDeleteApi(url, { idList: keyList });
      Message.success("删除成功");
      getList();
    } catch (err) {
      Message.error(MsgEnum.fail);
    }
  }
};

getList();

const selectedKeys = ref([]);

const rowSelection = reactive<TableRowSelection>({
  type: "checkbox",
  showCheckedAll: true,
  onlyCurrent: false,
});

const handleAction = () => {
  console.log(actionValue.value);
  const action = actionGroupOptions.find(
    (item) => item.value === actionValue.value
  );
  if (action) {
    action.callback(selectedKeys.value);
  }
};
</script>
<style lang="less">
.z_table {
  .z_table_head {
    display: flex;
    align-items: center;
    padding: 20px 20px 10px 20px;
    border-bottom: @z_border;
    position: relative;
    .action_create,
    .action_group,
    .action_search,
    .action_filter,
    .action_search_slot {
      margin-right: 10px;
    }
    .action_create {
    }
    .action_group {
      display: flex;
      align-items: center;
      button {
        margin-left: 10px;
      }
    }
    .action_filter {
      .arco-select {
        margin-right: 10px;
        &:last-child {
          margin-right: 0;
        }
      }
    }
    .action_search {
    }
    .action_search_slot {
    }
    .ation_refresh {
      position: absolute;
      right: 20px;
      width: 30px;
      height: 30px;
      border-radius: 4px;
      display: flex;
      justify-content: center;
      align-items: center;
      background-color: var(--color-fill-2);
      cursor: pointer;
    }
  }
  .z_table_body {
    padding: 10px 20px 20px 20px;
    > .arco-spin {
      width: 100%;
    }
    .z_table_pagination {
      display: flex;
      justify-content: center;
      margin-top: 10px;
    }
    .col_actions {
      button {
        margin-right: 10px;
        &:last-child {
          margin-right: 0;
        }
      }
    }
  }
}
</style>
